<?php
/////////////////////////////////////////////////////////////////////////////
// 
//
// Copyright (c) 2007 - 2009 www.shopnc.net
//
// workflow_copyright
// 
/////////////////////////////////////////////////////////////////////////////

/**
 * FILE_NAME : seride.php   FILE_PATH : \\classes\libraries
 * ....防CSRF攻击类
 *
 * @copyright workflow_system 
 * @author workflow Develop Team 
 * @version 4.28.2009
 */
define(TOKEN_NAME, "seride_token");
define(SOFT_NAME, "ShopNC Seride");
define(SOFT_VERS, "0.1");

class Seride extends CommonFrameWork {
	//********************************************************************************************************\\
	// 选择使用MD5或者sha1方式生成随机数
	var $hashing_algorithm = "md5";
	// 令牌的过期时间
	var $token_timeout = "10";
	var $abort = "Yes";
	// 是否记录日志
	var $error_log = "Yes";
	// 记录日志地址
	var	$log_filepath = "/log/seride_log.txt";
	var $session_referer = "";
	// 是否打印错误信息
	var $error_print = "Yes";
	var $custom_errormsg = "";
	var $custom_errorfile = "";
	var $hello_ZH;
	//********************************************************************************************************\\
	
	/**
	 * 构造函数
	 * @author workflow Develop Team     
	 * @param  
	 * @return int/bool/object/array/string
	 */
	function Seride(){
		$this->__construct();
	}
	function __construct(){
		parent::CommonFrameWork();
		$this->hello_ZH = $this->_lang['langCSerideHello'];
	}
	
	/**
     * 获得随机数
     *
     * @return string
     */
	function gen_hash() {
		if($this->hashing_algorithm == "sha1") {
			$hash = sha1(uniqid(rand(), true));
			$n = rand(1, 32);
		} else {
			$hash = md5(uniqid(rand(), true));
			$n = rand(1, 24);
		}
		$token = substr($hash, $n, 8);

		return $token;
	}

	/**
     * 清除令牌
     *
     * @param string $token
     */

	function destroy_stoken($token) {
		session_unregister($token);
	}

	/**
     * 建立令牌
     *
     * @return string
     */
	function create_stoken() {
		$token = $this->gen_hash();
		$this->destroy_stoken($token);
		session_register($token);
		$_SESSION[$token] = time();
		return $token;
	}

	function is_session($name) {
		if(isset($_SESSION[$name]))
		return TRUE;
		else
		return FALSE;
	}

	function seride_form() {
		$token = $this->create_stoken();
		return  "<input type=\"hidden\" name=\"" . TOKEN_NAME . "\" value=\"" . $token . "\">\n";
	}

	function seride_link($link) {
		$token = $this->create_stoken();
		$link .= "&" . TOKEN_NAME . "=" . $token . "";
		return $link;
	}

	function seride_log($id, $filepath, $session_referer) {
		$filepath = BasePath.$filepath;
		if(file_exists($filepath)) {
			$file = @fopen($filepath, "a");
		} else {
			$file = @fopen($filepath, "w");
			@fwrite($file, "SERIDE LOG FILE - Started at " . date("Y/m/d H:i", time()) . "\n");
			@fwrite($file, "=============================================\n\n");
		}

		$time = date("Y/m/d H:i", time());
		$session_referer_value = $_SESSION[$session_referer];
		$source_ip = $_SERVER['REMOTE_ADDR'];
		$action_page = $_SERVER['REQUEST_URI'];
		$request_method = $_SERVER['REQUEST_METHOD'];
		$referer = $_SERVER['HTTP_REFERER'];
		$useragent = $_SERVER['HTTP_USER_AGENT'];

		@fwrite($file, "[-!-] Malitious Request Found\n");
		@fwrite($file, "Time: $time\nError ID: $id\n");
		if($session_referer != "") {
			@fwrite($file, "Session Referer ($session_referer): $session_referer_value\n");
		}
		@fwrite($file, "Source IP: $source_ip\nAction Page: $action_page\nRequest Method: $request_method\nHTTP Referer: $referer\nHTTP User Agent: $useragent\n\n\n");
		@fclose($file);
	}

	function seride_print($id, $custom_errormsg, $custom_errorfile) {
		if($custom_errormsg != "" && $custom_errorfile == "") {
			echo "<div>" . $custom_errormsg . "</div>";
		} elseif($custom_errorfile != "" && $custom_errormsg == "") {
			if(file_exists($custom_errorfile)) {
				include($custom_errorfile);
			} else {
				echo "<div>ERROR: The custom error file specified can not be found. {$hello_ZH}</div>\n";
			}
		} else {

			// 中文文部分提醒
			echo "<div style=\"width: 400px; background-color: #cccccc; border: 2px solid #a0a0a0; padding: 10px; margin-left: auto; margin-right: auto; margin-top: 50px; font-size: 12px; font-family: Verdana;\">\n";
			echo "<div align=\"center\"><h2>".$this->_lang['langCSerideWarning']."</h2></div>\n";
			echo "<div>". $this->_lang['langCSerideWarningOne'] ."<br />". $this->_lang['langCSerideWarningTwo'] ."\n\n\n</div>";

			// 英文部分提醒
			echo "<div style=\"width: 340px; background-color: #cccccc; border: 2px solid #a0a0a0; padding: 10px; margin-left: auto; margin-right: auto; margin-top: 50px; font-size: 12px; font-family: Verdana;\">\n";
			echo "<div align=\"center\"><h2>ATTENTION!</h2></div>\n";
			echo "<div>A Malitious or not allowed request has been caught for the current action page.<br />It's possible that you fall as victim of an attempt of session hijacking.\n</div>";

			if(isset($id)) {
				switch($id) {
					// 如果令牌不存在
					case '1':
						echo "<div style=\"margin-top: 6px;\"><b>ERROR</b>: The request token doesn't appear to exist. {$this->hello_ZH}</div>\n";
						break;
						// Session 令牌不存在
					case '2':
						echo "<div style=\"margin-top: 6px;\"><b>ERROR</b>: The session token doesn't appear to exist. {$this->hello_ZH}</div>\n";
						break;
						// Session 令牌已经超时而不存在
					case '3':
						echo "<div style=\"margin-top: 6px;\"><b>ERROR</b>: The session token value doesn't appear to exist. {$this->hello_ZH}</div>\n";
						break;
						// 已经超时了
					case '4':
						echo "<div style=\"margin-top: 6px;\"><b>ERROR</b>: The request is timeout (time limit: " . $token_timeout . " minutes). {$this->hello_ZH}</div>\n";
						break;
					default:
						break;
				}
			}
			echo "</div>\n";
			echo "</div>\n";
			echo "<div style=\"width: 300px; margin-left: auto; margin-right: auto; font-family: Verdana; font-size: 11px; text-align: center;\">\n";
			echo "Powered by " . SOFT_NAME . " " . SOFT_VERS . " by <a href=\"http://www.shopnc.net\">www.shopnc.net</a>\n";
			echo "</div>\n";
		}
	}

	function seride_error($id) {

		// 是否写入日志
		if($this->error_log == "Yes") {
			$this->seride_log($id, $this->log_filepath, $this->session_referer);
		}
		// 错误显示开启
		if($this->error_print == "Yes") {
			//直接跳转
			$this->redirectPath('error','',$this->_lang['langCSerideOvertime']);
//			$this->seride_print($id, $this->custom_errormsg, $this->custom_errorfile);
//			exit;
		}
	}

	function seride_check() {
		if(isset($_REQUEST[TOKEN_NAME])) {
			// 检测SESSION令牌是否存在
			if($this->is_session($_REQUEST[TOKEN_NAME])) {
				if($_SESSION[$_REQUEST[TOKEN_NAME]] != '') {
					// 计算一下令牌的生存周期
					$token_age = time() - $_SESSION[$_REQUEST[TOKEN_NAME]];
					// 换算一个默认生命周期的秒数
					$token_timeout = $this->token_timeout*60;
					// 检测是否已经超过生命周期
					if($token_age <= $token_timeout) {
						$this->destroy_stoken($_REQUEST[TOKEN_NAME]);
						// 如果是ELSE那就是一个ERROR
					} else {
						$this->seride_error(4);
						$this->destroy_stoken($_REQUEST[TOKEN_NAME]);
						if($this->abort == "Yes") {
							exit();
						}
					}
				} else {
					$this->seride_error(3);
					$this->destroy_stoken($_REQUEST[TOKEN_NAME]);
					if($abort == "Yes") {
						exit();
					}
				}
			} else {
				$this->seride_error(2);
				$this->destroy_stoken($_REQUEST[TOKEN_NAME]);
				if($abort == "Yes") {
					exit();
				}
			}
		} else {

			$this->seride_error(1);
			$this->destroy_stoken($_REQUEST[TOKEN_NAME]);
			if($abort == "Yes") {
				exit();
			}
		}
	}

}
?>
